home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 July / EnigmA AMIGA RUN 29 (1998)(G.R. Edizioni)(IT)[!][issue 1998-07 & 08].iso / earcd / phase5 / ppcrelease / fd2inline / fd2inline.c < prev    next >
C/C++ Source or Header  |  1998-02-21  |  57KB  |  2,519 lines

  1. /******************************************************************************
  2.  *
  3.  * fd2inline
  4.  *
  5.  * Should be able to parse CBM fd files and generate vanilla inline calls
  6.  * for gcc. Works as a filter.
  7.  *
  8.  * by Wolfgang Baron, all rights reserved.
  9.  *
  10.  * improved, updated, simply made workable by Rainer F. Trunz 1/95
  11.  *
  12.  * Completely reworked Version, cleaned up and removed a whole lot of bugs
  13.  * found by Kamil Iskra.
  14.  *
  15.  * Expect miracles now (hopefully...). Ok, I am just kidding :)
  16.  *
  17.  * Version 0.99a by Rainer F. Trunz 6/95
  18.  *
  19.  * Version 0.99b and later by Kamil Iskra.
  20.  *
  21.  * Version 1.12 by Ralph Schmidt
  22.  *              PowerUP GCC/SAS extensions
  23.  *              I hope Kamil Iskra integrates that
  24.  *              in the official ADE version.
  25.  *
  26.  ******************************************************************************/
  27.  
  28. #include <ctype.h>
  29. #include <stddef.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34. /******************************************************************************
  35.  * The program has a few sort of class definitions, which are the result of
  36.  * object oriented thinking, to be imlemented in plain C. I just haven't
  37.  * had the time to learn C++ or install the compiler. The design does however
  38.  * improve robustness, which allows the source to be used over and over again.
  39.  * if you use this code, please leave a little origin note.
  40.  ******************************************************************************/
  41.  
  42. const static char version_str[]="$VER: fd2inline " VERSION " (12.12.97)";
  43.  
  44. /******************************************************************************
  45.  * These are general definitions including types for defining registers etc.
  46.  ******************************************************************************/
  47.  
  48. #ifdef DEBUG
  49. #define DBP(a) a
  50. #else /* !DEBUG */
  51. #define DBP(a)
  52. #endif /* !DEBUG */
  53.  
  54. #if (defined(__GNUC__) || defined(__SASC)) && 0
  55. #define INLINE __inline /* Gives 20% *larger* executable with GCC?! */
  56. #else
  57. #define INLINE
  58. #endif
  59.  
  60. #define REGS 16  /* d0=0,...,a7=15 */
  61. #define FDS 1000
  62.  
  63. typedef enum
  64. {
  65.     d0, d1, d2, d3, d4, d5, d6, d7, a0, a1, a2, a3, a4, a5, a6, a7, illegal
  66. } regs;
  67.  
  68. typedef unsigned char uchar, shortcard;
  69. typedef unsigned long ulong;
  70.  
  71. #ifndef    FALSE
  72. #define    FALSE    0
  73. #endif
  74. #ifndef    TRUE
  75. #define    TRUE    1
  76. #endif
  77.  
  78. typedef enum { false, nodef, real_error } Error;
  79.  
  80. enum {NEW, OLD, STUBS, PROTO, PRAGMA} output_mode=NEW;
  81.  
  82. short    PowerUP=0;
  83.  
  84. char BaseName[32], BaseNamU[32],  BaseNamL[32];
  85.  
  86. const static char *LibExcTable[]=
  87. {
  88.     "BattClockBase",            "Node",
  89.     "BattMemBase",                "Node",
  90.     "ConsoleDevice",            "Device",
  91.     "DiskBase",                "DiskResource",
  92.     "DOSBase",                "DosLibrary",
  93.     "SysBase",                "ExecBase",
  94.     "ExpansionBase",            "ExpansionBase",
  95.     "GfxBase",                "GfxBase",
  96.     "InputBase",                "Device",
  97.     "IntuitionBase",            "IntuitionBase",
  98.     "LocaleBase",                "LocaleBase",
  99.     "MathIeeeDoubBasBase",    "MathIEEEBase",
  100.     "MathIeeeDoubTransBase","MathIEEEBase",
  101.     "MathIeeeSingBasBase",    "MathIEEEBase",
  102.     "MathIeeeSingTransBase","MathIEEEBase",
  103.     "MiscBase",                "Node",
  104.     "PotgoBase",                "Node",
  105.     "RamdriveDevice",            "Device",
  106.     "RealTimeBase",                "RealTimeBase",
  107.     "RexxSysBase",                "RxsLib",
  108.     "TimerBase",                "Device",
  109.     "UtilityBase",                "UtilityBase"
  110. };
  111. const char *StdLib; /* global lib-name ptr */
  112.  
  113. /*******************************************
  114.  * just some support functions, no checking
  115.  *******************************************/
  116.  
  117. char*
  118. NewString(char** new, const char* old)
  119. {
  120.     const char *high;
  121.     ulong len;
  122.  
  123.     while (*old && (*old==' ' || *old=='\t'))
  124.         old++;
  125.     len=strlen(old);
  126.     for (high=old+len-1; high>=old && (*high==' ' || *high=='\t'); high--);
  127.     high++;
  128.     len=high-old;
  129.     *new=malloc(1+len);
  130.     if (*new)
  131.     {
  132.         strncpy(*new, old, len);
  133.         (*new)[len]='\0';
  134.     }
  135.     else
  136.         fprintf(stderr, "no mem for string\n");
  137.     return *new;
  138. }
  139.  
  140. static INLINE void
  141. illparams(const char* funcname)
  142. {
  143.     fprintf(stderr, "%s: illegal Parameters\n", funcname);
  144. }
  145.  
  146. static INLINE const char*
  147. RegStr(regs reg)
  148. {
  149.     const static char *myregs[]=
  150.     {
  151.         "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  152.         "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "illegal"
  153.     };
  154.  
  155.     if (reg>illegal)
  156.         reg=illegal;
  157.     if (reg<d0)
  158.         reg=d0;
  159.     return myregs[reg];
  160. }
  161.  
  162. /******************************************************************************
  163.  *    StrNRBrk
  164.  *
  165.  * searches string in from position at downwards, as long as in does not
  166.  * contain any character in not.
  167.  *
  168.  ******************************************************************************/
  169.  
  170. const char*
  171. StrNRBrk(const char* in, const char* not, const char* at)
  172. {
  173.     const char *chcheck;
  174.     Error ready;
  175.  
  176.     chcheck=""; /* if at<in, the result will be NULL */
  177.     for (ready=false; ready==false && at>=in;)
  178.     {
  179.         for (chcheck=not; *chcheck && *chcheck != *at; chcheck++);
  180.         if (*chcheck)
  181.             ready=real_error;
  182.         else
  183.             at--;
  184.     }
  185.     DBP(fprintf(stderr, "{%c}", *chcheck));
  186.     return *chcheck ? at : NULL;
  187. }
  188.  
  189. /*
  190.   Our own "strupr", since it is a non-standard function.
  191. */
  192. void
  193. StrUpr(char* str)
  194. {
  195.     while (*str)
  196.     {
  197.         *str=toupper(*str);
  198.         str++;
  199.     }
  200. }
  201.  
  202. /******************************************************************************
  203.  *    CLASS fdFile
  204.  *
  205.  * stores a file with a temporary buffer (static length, sorry), a line number,
  206.  * an offset (used for library offsets and an error field.
  207.  * When there's no error, line will contain line #lineno and offset will be
  208.  * the last offset set by the interpretation of the last line. If there's been
  209.  * no ##bias line, this field assumes a bias of 30, which is the standard bias.
  210.  * It is assumed offsets are always negative.
  211.  ******************************************************************************/
  212.  
  213. #define fF_BUFSIZE 1024
  214.  
  215. /* all you need to know about an fdFile you parse */
  216.  
  217. typedef struct
  218. {
  219.     FILE*    file;                    /* the file we're reading from        */
  220.     char    line[fF_BUFSIZE];    /* the current line                        */
  221.     ulong    lineno;                /* current line number                    */
  222.     long    offset;                /* current fd offset (-bias)            */
  223.     Error    error;                /* is everything o.k.                    */
  224.     char    private;                /* are we in ##public or ##private    */
  225. } fdFile;
  226.  
  227. fdFile*
  228. fF_ctor            (const char* fname);
  229. static void
  230. fF_dtor            (fdFile* obj);
  231. static void
  232. fF_SetError        (fdFile* obj, Error error);
  233. static void
  234. fF_SetOffset    (fdFile* obj, long at);
  235. Error
  236. fF_readln        (fdFile* obj);
  237. static Error
  238. fF_GetError        (const fdFile* obj);
  239. static long
  240. fF_GetOffset    (const fdFile* obj);
  241. char*
  242. fF_FuncName        (fdFile* obj); /* return name or null */
  243. static void
  244. fF_SetPrivate    (fdFile* obj, char priv);
  245. static char
  246. fF_GetPrivate    (const fdFile* obj);
  247.  
  248. static INLINE void
  249. fF_dtor(fdFile* obj)
  250. {
  251.   fclose(obj->file);
  252.   free(obj);
  253. }
  254.  
  255. static INLINE void
  256. fF_SetError(fdFile* obj, Error error)
  257. {
  258.     if (obj)
  259.         obj->error=error;
  260.     else
  261.         illparams("fF_SetError");
  262. }
  263.  
  264. static INLINE void
  265. fF_SetOffset(fdFile* obj, long at)
  266. {
  267.     if (obj)
  268.         obj->offset= at;
  269.     else
  270.         illparams("fFSetOffset");
  271. }
  272.  
  273. static INLINE void
  274. fF_SetPrivate(fdFile* obj, char priv)
  275. {
  276.   if (obj)
  277.     obj->private=priv;
  278.   else
  279.     illparams("fF_SetPrivate");
  280. }
  281.  
  282. fdFile*
  283. fF_ctor(const char* fname)
  284. {
  285.     fdFile *result;
  286.  
  287.     if (fname)
  288.     {
  289.         result=malloc(sizeof(fdFile));
  290.         if (result)
  291.         {
  292.             result->file=fopen(fname, "r");
  293.             if (result->file)
  294.             {
  295.                 result->lineno=0;
  296.                 fF_SetOffset(result, -30);
  297.                 fF_SetError(result, false);
  298.                 fF_SetPrivate(result, 0);
  299.                 result->line[0]='\0';
  300.             }
  301.             else
  302.             {
  303.                 free(result);
  304.                 result=NULL;
  305.             }
  306.         }
  307.     }
  308.     else
  309.     {
  310.         result=NULL;
  311.         illparams("fF_ctor");
  312.     }
  313.     return result;
  314. }
  315.  
  316. Error
  317. fF_readln(fdFile* obj)
  318. {
  319.     char *low, *bpoint;
  320.     long glen,    /* the length we read until now */
  321.     len;            /* the length of the last segment */
  322.  
  323.     if (obj)
  324.     {
  325.         low=obj->line;
  326.         glen=0;
  327.  
  328.         for (;;)
  329.         {
  330.             obj->lineno++;
  331.             if (!fgets(low, fF_BUFSIZE-1-glen, obj->file))
  332.             {
  333.                 fF_SetError(obj, real_error);
  334.                 obj->line[0]='\0';
  335.                 return real_error;
  336.             }
  337.             if (low==strpbrk(low, "*#/"))
  338.             {
  339.                 DBP(fprintf(stderr, "in# %s\n", obj->line));
  340.                 return false;
  341.             }
  342.             len=strlen(low);
  343.             bpoint=low+len-1;
  344.             while (len && isspace(*bpoint))
  345.             {
  346.                 bpoint--;
  347.                 len--;
  348.             }
  349.             if (*bpoint==';' || *bpoint==')')
  350.             {
  351.                 DBP(fprintf(stderr, "\nin: %s\n", obj->line));
  352.                 return false;
  353.             }
  354.             glen+=len;
  355.             low+=len;
  356.             if (glen>=fF_BUFSIZE-10) /* somewhat pessimistic? */
  357.             {
  358.                 fF_SetError(obj, real_error);
  359.                 fprintf(stderr, "line %lu too long.\n", obj->lineno);
  360.                 return real_error;
  361.             }
  362.             DBP(fprintf(stderr, "+"));
  363.         }
  364.     }
  365.     illparams("fF_readln");
  366.     return real_error;
  367. }
  368.  
  369. static INLINE Error
  370. fF_GetError(const fdFile* obj)
  371. {
  372.     if (obj)
  373.         return obj->error;
  374.     illparams("fF_GetError");
  375.     return real_error;
  376. }
  377.  
  378. static INLINE long
  379. fF_GetOffset(const fdFile* obj)
  380. {
  381.     if (obj)
  382.         return obj->offset;
  383.     illparams("fF_GetOffset");
  384.     return -1;
  385. }
  386.  
  387. /******************************************************************************
  388.  * fF_FuncName
  389.  *
  390.  * checks if it can find a function-name and return it's address, or NULL
  391.  * if the current line does not seem to contain one. The return value will
  392.  * be a pointer into a malloced buffer, thus the caller will have to free().
  393.  ******************************************************************************/
  394.  
  395. char*
  396. fF_FuncName(fdFile* obj)
  397. {
  398.     const char *lower;
  399.     const char *upper;
  400.     char *buf;
  401.     long obraces;    /* count of open braces */
  402.     Error ready;    /* ready with searching */
  403.  
  404.     if (!obj || fF_GetError(obj)==real_error)
  405.     {
  406.         illparams("fF_FuncName");
  407.         return NULL;
  408.     }
  409.  
  410.     lower=obj->line;
  411.     while (*lower && (*lower==' ' || *lower=='\t'))
  412.         lower++;
  413.  
  414.     if (!*lower || (!isalpha(*lower) && *lower!='_'))
  415.     {
  416.         fF_SetError(obj, nodef);
  417.         return NULL;
  418.     }
  419.  
  420.     while (*lower)
  421.     {
  422.         if (!isalnum(*lower) && !isspace(*lower) && *lower!='*' && *lower!=','
  423.         && *lower!='.' && *lower!=';' && *lower!='(' && *lower!=')' &&
  424.         *lower!='[' && *lower!=']' && *lower!='_' && *lower!='\\')
  425.         {
  426.             fF_SetError(obj, nodef);
  427.             return NULL;
  428.         }
  429.         lower++;
  430.     }
  431.  
  432.     lower=NULL;
  433.     buf=NULL;
  434.  
  435.     if (obj && fF_GetError(obj)==false)
  436.     {
  437.         if ((upper=strrchr(obj->line, ')'))!=0)
  438.         {
  439.             DBP(fprintf(stderr, "end:%s:", upper));
  440.  
  441.             for (obraces=1, ready=false; ready==false; upper=lower)
  442.             {
  443.                 lower=StrNRBrk(obj->line, "()", --upper);
  444.                 if (lower)
  445.                 {
  446.                     switch (*lower)
  447.                     {
  448.                         case ')':
  449.                             obraces++;
  450.                             DBP(fprintf(stderr, " )%ld%s", obraces, lower));
  451.                             break;
  452.                         case '(':
  453.                             obraces--;
  454.                             DBP(fprintf(stderr, " (%ld%s", obraces, lower));
  455.                             if (!obraces)
  456.                                 ready=nodef;
  457.                             break;
  458.                         default:
  459.                             fprintf(stderr, "faulty StrNRBrk\n");
  460.                     }
  461.                 }
  462.                 else
  463.                 {
  464.                     fprintf(stderr, "'(' or ')' expected in line %lu.\n",
  465.                         obj->lineno);
  466.                     ready=real_error;
  467.                 }
  468.             }
  469.             if (ready==nodef) /* we found the matching '(' */
  470.             {
  471.                 long newlen;
  472.                 const char* name;
  473.  
  474.                 upper--;
  475.  
  476.                 while (upper>=obj->line && (*upper==' ' || *upper=='\t'))
  477.                     upper--;
  478.  
  479.                 lower=StrNRBrk(obj->line, " \t*)", upper);
  480.  
  481.                 if (!lower)
  482.                     lower=obj->line;
  483.                 else
  484.                     lower++;
  485.  
  486.                 for (name=lower; name<=upper; name++)
  487.                     if (!isalnum(*name) && *name!='_')
  488.                     {
  489.                         fF_SetError(obj, nodef);
  490.                         return NULL;
  491.                     }
  492.  
  493.                 newlen=upper-lower+1;
  494.                 buf=malloc(newlen+1);
  495.  
  496.                 if (buf)
  497.                 {
  498.                     strncpy(buf, lower, newlen);
  499.                     buf[newlen]='\0';
  500.                 }
  501.                 else
  502.                     fprintf(stderr, "no mem for fF_FuncName");
  503.             }
  504.         }
  505.     }
  506.     else
  507.         illparams("fF_FuncName");
  508.     return buf;
  509. }
  510.  
  511. static INLINE char
  512. fF_GetPrivate(const fdFile* obj)
  513. {
  514.     if (obj)
  515.         return obj->private;
  516.     illparams("fF_GetPrivate");
  517.     return 0;
  518. }
  519.  
  520. /*********************
  521.  *    CLASS fdDef    *
  522.  *********************/
  523.  
  524. typedef struct
  525. {
  526.     char*    name;
  527.     char*    type;
  528.     long    offset;
  529.     regs    reg[REGS];
  530.     char*    param[REGS];
  531.     char*    proto[REGS];
  532.     regs    funcpar; /* number of argument that has type "pointer to function" */
  533. } fdDef;
  534.  
  535. fdDef*
  536. fD_ctor                (void);
  537. void
  538. fD_dtor                (fdDef* obj);
  539. static void
  540. fD_NewName            (fdDef* obj, const char* newname);
  541. void
  542. fD_NewParam            (fdDef* obj, shortcard at, const char* newstr);
  543. void
  544. fD_NewProto            (fdDef* obj, shortcard at, char* newstr);
  545. static void
  546. fD_NewReg            (fdDef* obj, shortcard at, regs reg);
  547. static void
  548. fD_NewType            (fdDef* obj, const char* newstr);
  549. static void
  550. fD_SetOffset        (fdDef* obj, long off);
  551. Error
  552. fD_parsefd            (fdDef* obj, fdFile* infile);
  553. Error
  554. fD_parsepr            (fdDef* obj, fdFile* infile);
  555. static const char*
  556. fD_GetName            (const fdDef* obj);
  557. static long
  558. fD_GetOffset        (const fdDef* obj);
  559. static const char*
  560. fD_GetParam            (const fdDef* obj, shortcard at);
  561. static regs
  562. fD_GetReg            (const fdDef* obj, shortcard at);
  563. static const char*
  564. fD_GetRegStr        (const fdDef* obj, shortcard at);
  565. static const char*
  566. fD_GetType            (const fdDef* obj);
  567. static shortcard
  568. fD_ParamNum            (const fdDef* obj);
  569. static shortcard
  570. fD_ProtoNum            (const fdDef* obj);
  571. static shortcard
  572. fD_RegNum            (const fdDef* obj);
  573. int
  574. fD_cmpName            (const void* big, const void* small);
  575. void
  576. fD_write                (FILE* outfile, const fdDef* obj);
  577. static shortcard
  578. fD_GetFuncParNum    (const fdDef* obj);
  579. static void
  580. fD_SetFuncParNum    (fdDef* obj, shortcard at);
  581. static void
  582. fD_adjustargnames(fdDef *obj);
  583.  
  584. fdDef **arrdefs;
  585. long fds;
  586.  
  587. char *fD_nostring="";
  588.  
  589. fdDef*
  590. fD_ctor(void)
  591. {
  592.     fdDef *result;
  593.     regs count;
  594.  
  595.     result=malloc(sizeof(fdDef));
  596.  
  597.     if (result)
  598.     {
  599.         result->name=fD_nostring;
  600.         result->type=fD_nostring;
  601.         result->funcpar=illegal;
  602.  
  603.         for (count=d0; count<illegal; count++ )
  604.         {
  605.             result->reg[count]=illegal;
  606.             result->param[count]=fD_nostring; /* if (!strlen) dont't free() */
  607.             result->proto[count]=fD_nostring;
  608.         }
  609.     }
  610.     return result;
  611. }
  612.  
  613. /* free all resources and make the object as illegal as possible */
  614.  
  615. void
  616. fD_dtor(fdDef* obj)
  617. {
  618.     regs count;
  619.  
  620.     if (obj)
  621.     {
  622.         if (!obj->name)
  623.             fprintf(stderr, "fD_dtor: null name");
  624.         else
  625.             if (obj->name!=fD_nostring)
  626.                 free(obj->name);
  627.  
  628.         if (!obj->type)
  629.             fprintf(stderr, "fD_dtor: null type");
  630.         else
  631.             if (obj->type!=fD_nostring)
  632.                 free(obj->type);
  633.  
  634.         obj->name=obj->type=NULL;
  635.  
  636.         for (count=d0; count<illegal; count++)
  637.         {
  638.             obj->reg[count]=illegal;
  639.  
  640.             if (!obj->param[count])
  641.                 fprintf(stderr, "fD_dtor: null param");
  642.             else
  643.                 if (obj->param[count]!=fD_nostring)
  644.                     free(obj->param[count]);
  645.  
  646.             if (!obj->proto[count])
  647.                 fprintf(stderr, "fD_dtor: null proto");
  648.             else
  649.                 if (obj->proto[count]!=fD_nostring)
  650.                     free(obj->proto[count]);
  651.  
  652.             obj->param[count]=obj->proto[count]=NULL;
  653.         }
  654.  
  655.         free(obj);
  656.     }
  657.     else
  658.         fprintf(stderr, "fd_dtor(NULL)\n");
  659. }
  660.  
  661. static INLINE void
  662. fD_NewName(fdDef* obj, const char* newname)
  663. {
  664.     if (obj && newname)
  665.     {
  666.         if (obj->name && obj->name!=fD_nostring)
  667.             free(obj->name);
  668.         if (!NewString(&obj->name, newname))
  669.             obj->name=fD_nostring;
  670.     }
  671.     else
  672.         illparams("fD_NewName");
  673. }
  674.  
  675. void
  676. fD_NewParam(fdDef* obj, shortcard at, const char* newstr)
  677. {
  678.     char *pa;
  679.  
  680.     if (newstr && obj && at<illegal)
  681.     {
  682.         pa=obj->param[at];
  683.  
  684.         if (pa && pa!=fD_nostring)
  685.             free(pa);
  686.  
  687.         while (*newstr==' ' || *newstr=='\t')
  688.             newstr++;
  689.  
  690.         if (NewString(&pa, newstr))
  691.             obj->param[at]=pa;
  692.         else
  693.             obj->param[at]=fD_nostring;
  694.     }
  695.     else
  696.         illparams("fD_NewParam");
  697. }
  698.  
  699. /* get first free *reg or illegal */
  700.  
  701. static INLINE shortcard
  702. fD_RegNum(const fdDef* obj)
  703. {
  704.     shortcard count;
  705.  
  706.     if (obj)
  707.     {
  708.         for (count=d0; count<illegal && obj->reg[count]!=illegal; count++);
  709.         return count;
  710.     }
  711.     else
  712.     {
  713.         illparams("fD_RegNum");
  714.         return illegal;
  715.     }
  716. }
  717.  
  718. static INLINE void
  719. fD_NewReg(fdDef* obj, shortcard at, regs reg)
  720. {
  721.     if (obj && at<illegal && reg>=d0 && reg<=illegal)
  722.         obj->reg[at]=reg;
  723.     else
  724.         illparams("fD_NewReg");
  725. }
  726.  
  727. static INLINE regs
  728. fD_GetReg(const fdDef* obj, shortcard at)
  729. {
  730.     if (obj && at<illegal)
  731.         return obj->reg[at];
  732.     else
  733.     {
  734.         illparams("fD_GetReg");
  735.         return illegal;
  736.     }
  737. }
  738.  
  739. static INLINE shortcard
  740. fD_GetFuncParNum(const fdDef* obj)
  741. {
  742.     if (obj)
  743.         return (shortcard)obj->funcpar;
  744.     else
  745.     {
  746.         illparams("fD_GetFuncParNum");
  747.         return illegal;
  748.     }
  749. }
  750.  
  751. static INLINE void
  752. fD_SetFuncParNum(fdDef* obj, shortcard at)
  753. {
  754.     if (obj && at<illegal)
  755.         obj->funcpar=at;
  756.     else
  757.         illparams("fD_SetFuncParNum");
  758. }
  759.  
  760. void
  761. fD_NewProto(fdDef* obj, shortcard at, char* newstr)
  762. {
  763.     char *pr;
  764.  
  765.     if (newstr && obj && at<illegal)
  766.     {
  767.         char *t, arr[200]; /* I hope 200 will be enough... */
  768.         int numwords=1;
  769.         pr=obj->proto[at];
  770.  
  771.         if (pr && pr!=fD_nostring)
  772.             free(pr);
  773.  
  774.         while (*newstr==' ' || *newstr=='\t')
  775.             newstr++; /* Skip leading spaces */
  776.  
  777.         t=arr;
  778.         while ((*t++=*newstr)!=0)
  779.         {
  780.             /* Copy the rest, counting number of words */
  781.             if ((*newstr==' ' || *newstr=='\t') && newstr[1] && newstr[1]!=' ' &&
  782.             newstr[1]!='\t')
  783.                 numwords++;
  784.             newstr++;
  785.         }
  786.  
  787.         t=arr+strlen(arr)-1;
  788.         while (*t==' ' || *t=='\t')
  789.             t--;
  790.         t[1]='\0'; /* Get rid of tailing spaces */
  791.         if (at!=fD_GetFuncParNum(obj))
  792.         {
  793.             if (numwords>1) /* One word - must be type */
  794.                 if (*t!='*')
  795.                 {
  796.                     /* '*' on the end - no parameter name used */
  797.                     while (*t!=' ' && *t!='\t' && *t!='*')
  798.                         t--;
  799.                     t++;
  800.                     if (strcmp(t, "char") && strcmp(t, "short") && strcmp(t, "int")
  801.                     && strcmp(t, "long"))
  802.                     {
  803.                         /* Not one of applicable keywords - must be parameter name.
  804.                             Get rid of it. */
  805.                         t--;
  806.                         while (*t==' ' || *t=='\t')
  807.                             t--;
  808.                         t[1]='\0';
  809.                     }
  810.                 }
  811.         }
  812.         else
  813.         {
  814.             /* Parameter of type "pointer to function". */
  815.             char *end;
  816.             t=strchr(arr, '(');
  817.             while (*t++!='*');
  818.             end=strchr(t, ')');
  819.             memmove(t+2, end, strlen(end)+1);
  820.             *t='%';
  821.             t[1]='s';
  822.         }
  823.  
  824.         if (NewString(&pr, arr))
  825.         {
  826.             obj->proto[at]=pr;
  827.             while (*pr==' ' || *pr=='\t')
  828.                 pr++;
  829.             if (!stricmp(pr, "double"))
  830.             {
  831.                 /* "double" needs two data registers */
  832.                 int count, regs=fD_RegNum(obj);
  833.                 for (count=at+1; count<regs; count++)
  834.                     fD_NewReg(obj, count, fD_GetReg(obj, count+1));
  835.             }
  836.         }
  837.         else
  838.             obj->proto[at]=fD_nostring;
  839.     }
  840.     else
  841.         illparams("fD_NewProto");
  842. }
  843.  
  844. static INLINE void
  845. fD_NewType(fdDef* obj, const char* newtype)
  846. {
  847.     if (obj && newtype)
  848.     {
  849.         if (obj->type && obj->type!=fD_nostring)
  850.             free(obj->type);
  851.         if (!NewString(&obj->type, newtype))
  852.             obj->type=fD_nostring;
  853.     }
  854.     else
  855.         illparams("fD_NewType");
  856. }
  857.  
  858. static INLINE void
  859. fD_SetOffset(fdDef* obj, long off)
  860. {
  861.     if (obj)
  862.         obj->offset=off;
  863.     else
  864.         illparams("fD_SetOffset");
  865. }
  866.  
  867. static INLINE const char*
  868. fD_GetName(const fdDef* obj)
  869. {
  870.     if (obj && obj->name)
  871.         return obj->name;
  872.     else
  873.     {
  874.         illparams("fD_GetName");
  875.         return fD_nostring;
  876.     }
  877. }
  878.  
  879. static INLINE long
  880. fD_GetOffset(const fdDef* obj)
  881. {
  882.     if (obj)
  883.         return obj->offset;
  884.     else
  885.     {
  886.         illparams("fD_GetOffset");
  887.         return 0;
  888.     }
  889. }
  890.  
  891. static INLINE const char*
  892. fD_GetProto(const fdDef* obj, shortcard at)
  893. {
  894.     if (obj && at<illegal && obj->proto[at])
  895.         return obj->proto[at];
  896.     else
  897.     {
  898.         illparams("fD_GetProto");
  899.         return fD_nostring;
  900.     }
  901. }
  902.  
  903. static INLINE const char*
  904. fD_GetParam(const fdDef* obj, shortcard at)
  905. {
  906.     if (obj && at<illegal && obj->param[at])
  907.         return obj->param[at];
  908.     else
  909.     {
  910.         illparams("fD_GetParam");
  911.         return fD_nostring;
  912.     }
  913. }
  914.  
  915. static INLINE const char*
  916. fD_GetRegStr(const fdDef* obj, shortcard at)
  917. {
  918.     if (obj && at<illegal)
  919.         return RegStr(obj->reg[at]);
  920.     else
  921.     {
  922.         illparams("fD_GetReg");
  923.         return RegStr(illegal);
  924.     }
  925. }
  926.  
  927. static INLINE const char*
  928. fD_GetType(const fdDef* obj)
  929. {
  930.     if (obj && obj->type)
  931.         return obj->type;
  932.     else
  933.     {
  934.         illparams("fD_GetType");
  935.         return fD_nostring;
  936.     }
  937. }
  938.  
  939. /* get first free param or illegal */
  940.  
  941. static INLINE shortcard
  942. fD_ParamNum(const fdDef* obj)
  943. {
  944.     shortcard count;
  945.  
  946.     if (obj)
  947.     {
  948.         for (count=d0; count<illegal && obj->param[count]!=fD_nostring;
  949.         count++);
  950.         return count;
  951.     }
  952.     else
  953.     {
  954.         illparams("fD_ParamNum");
  955.         return illegal;
  956.     }
  957. }
  958.  
  959. static INLINE shortcard
  960. fD_ProtoNum(const fdDef* obj)
  961. {
  962.     shortcard count;
  963.  
  964.     if (obj)
  965.     {
  966.         for (count=d0; count<illegal && obj->proto[count]!=fD_nostring;
  967.         count++);
  968.         return count;
  969.     }
  970.     else
  971.     {
  972.         illparams("fD_ProtoNum");
  973.         return illegal;
  974.     }
  975. }
  976.  
  977. /******************************************************************************
  978.  *    fD_parsefd
  979.  *
  980.  *  parse the current line. Needs to copy input, in order to insert \0's
  981.  *  RETURN
  982.  *    fF_GetError(infile):
  983.  *    false = read a definition.
  984.  *    nodef = not a definition on line (so try again)
  985.  *    error = real error
  986.  ******************************************************************************/
  987.  
  988. Error
  989. fD_parsefd(fdDef* obj, fdFile* infile)
  990. {
  991.     enum parse_info { name, params, regs, ready } parsing;
  992.     char *buf, *bpoint, *bnext;
  993.     ulong index;
  994.  
  995.     if (obj && infile && fF_GetError(infile)==false)
  996.     {
  997.         parsing=name;
  998.  
  999.         if (!NewString(&buf, infile->line))
  1000.         {
  1001.             fprintf(stderr, "no mem for line %lu\n", infile->lineno);
  1002.             fF_SetError(infile, real_error);
  1003.         }
  1004.         bpoint=buf; /* so -Wall keeps quiet */
  1005.  
  1006.         /* try to parse the line until there's an error or we are done */
  1007.  
  1008.         while (parsing!=ready && fF_GetError(infile)==false)
  1009.         {
  1010.             switch (parsing)
  1011.             {
  1012.                 case name:
  1013.                     switch (buf[0])
  1014.                     {
  1015.                         case '#':
  1016.                             if (strncmp("##base", buf, 6)==0)
  1017.                             {
  1018.                                 bnext=buf+6;
  1019.                                 while (*bnext==' ' || *bnext=='\t' || *bnext=='_')
  1020.                                     bnext++;
  1021.                                 strcpy(BaseName, bnext);
  1022.                                 BaseName[strlen(BaseName)-1]='\0';
  1023.                             }
  1024.                             else
  1025.                                 if (strncmp("##bias", buf, 6)==0)
  1026.                                 {
  1027.                                     if (!sscanf(buf+6, "%ld", &infile->offset))
  1028.                                     {
  1029.                                         fprintf(stderr, "illegal ##bias in line %lu: %s\n",
  1030.                                             infile->lineno, infile->line);
  1031.                                         fF_SetError(infile, real_error);
  1032.                                         break; /* avoid nodef */
  1033.                                     }
  1034.                                     else
  1035.                                     {
  1036.                                         if (fF_GetOffset(infile)>0)
  1037.                                             fF_SetOffset(infile, -fF_GetOffset(infile));
  1038.                                         DBP(fprintf(stderr, "set offset to %ld\n",
  1039.                                             fFGetOffset(infile)));
  1040.                                     }
  1041.                                 }
  1042.                                 else
  1043.                                 {
  1044.                                     if (strncmp("##private", buf, 9)==0)
  1045.                                         fF_SetPrivate(infile, 1);
  1046.                                     else
  1047.                                         if (strncmp("##public", buf, 8)==0)
  1048.                                             fF_SetPrivate(infile, 0);
  1049.                                 }
  1050.                             /* drop through for error comment */
  1051.  
  1052.                         case '*':
  1053.                             /* try again somewhere else */
  1054.                             fF_SetError(infile, nodef);
  1055.                                 break;
  1056.  
  1057.                         default:
  1058.                             /* assume a regular line here */
  1059.                             if (fF_GetPrivate(infile))
  1060.                             {
  1061.                                 /* don't store names of privates */
  1062.                                 fF_SetError(infile, nodef);
  1063.                                 fF_SetOffset(infile, fF_GetOffset(infile)-6);
  1064.                                 break;
  1065.                             }
  1066.                             parsing=name; /* switch (parsing) */
  1067.                             for (index=0; buf[index] && buf[index]!='('; index++);
  1068.  
  1069.                             if (!buf[index])
  1070.                             {
  1071.                                 /* oops, no fd ? */
  1072.                                 fprintf(stderr, "not an fd, line %lu: %s\n",
  1073.                                     infile->lineno, buf /* infile->line */);
  1074.                                 fF_SetError(infile, nodef);
  1075.                             } /* maybe next time */
  1076.                             else
  1077.                             {
  1078.                                 buf[index]=0;
  1079.  
  1080.                                 fD_NewName(obj, buf);
  1081.                                 fD_SetOffset(obj, fF_GetOffset(infile));
  1082.  
  1083.                                 bpoint=buf+index+1;
  1084.                                 parsing=params; /* continue the loop */
  1085.                             }
  1086.                     }
  1087.                     break;
  1088.  
  1089.                 case params:
  1090.                 {
  1091.                     char *bptmp; /* needed for fD_NewParam */
  1092.  
  1093.                     /* look for parameters now */
  1094.  
  1095.                     for (bnext = bpoint; *bnext && *bnext!=',' && *bnext!=')';
  1096.                     bnext++);
  1097.  
  1098.                     if (*bnext)
  1099.                     {
  1100.                         bptmp=bpoint;
  1101.  
  1102.                         if (*bnext == ')')
  1103.                         {
  1104.                             if (bnext[1] != '(')
  1105.                             {
  1106.                                 fprintf(stderr, "registers expected in line %lu: %s\n",
  1107.                                     infile->lineno, infile->line);
  1108.                                 fF_SetError(infile, nodef);
  1109.                             }
  1110.                             else
  1111.                             {
  1112.                                 parsing=regs;
  1113.                                 bpoint=bnext+2;
  1114.                             }
  1115.                         }
  1116.                         else
  1117.                             bpoint = bnext+1;
  1118.  
  1119.                         /* terminate string and advance to next item */
  1120.  
  1121.                         *bnext='\0';
  1122.                         fD_NewParam(obj, fD_ParamNum(obj), bptmp);
  1123.                     }
  1124.                     else
  1125.                     {
  1126.                         fF_SetError(infile, nodef);
  1127.                         fprintf(stderr, "param expected in line %lu: %s\n",
  1128.                             infile->lineno, infile->line);
  1129.                     }
  1130.                     break;  /* switch parsing */
  1131.                 }
  1132.  
  1133.                 case regs:
  1134.                     /* look for parameters now */
  1135.  
  1136.                     for (bnext=bpoint; *bnext && *bnext!='/' && *bnext!=',' &&
  1137.                     *bnext!=')'; bnext++);
  1138.  
  1139.                     if (*bnext)
  1140.                     {
  1141.                         if (')'==*bnext)
  1142.                         {
  1143.                             /* wow, we've finished */
  1144.                             fF_SetOffset(infile, fF_GetOffset(infile)-6);
  1145.                             parsing=ready;
  1146.                         }
  1147.                         *bnext = '\0';
  1148.  
  1149.                         bpoint[0]=tolower(bpoint[0]);
  1150.  
  1151.                         if ((bpoint[0]=='d' || bpoint[0]=='a') && bpoint[1]>='0' &&
  1152.                         bpoint[1]<='8' && bnext==bpoint+2)
  1153.                             fD_NewReg(obj, fD_RegNum(obj),
  1154.                                 bpoint[1]-'0'+(bpoint[0]=='a'? 8 : 0));
  1155.                         else
  1156.                             if (bnext!=bpoint)
  1157.                             {
  1158.                                 /* it is when our function is void */
  1159.                                 fprintf(stderr, "illegal register %s in line %ld\n",
  1160.                                     bpoint, infile->lineno);
  1161.                                 fF_SetError(infile, nodef);
  1162.                             }
  1163.                         bpoint = bnext+1;
  1164.                     }
  1165.                     else
  1166.                     {
  1167.                         fF_SetError(infile, nodef);
  1168.                         fprintf(stderr, "reg expected in line %lu\n",
  1169.                             infile->lineno);
  1170.                     }
  1171.                     break; /* switch parsing */
  1172.  
  1173.                 case ready:
  1174.                     fprintf(stderr, "internal error, use another compiler.\n");
  1175.                     break;
  1176.             }
  1177.         }
  1178.  
  1179.         free(buf);
  1180.         return fF_GetError(infile);
  1181.     }
  1182.     else
  1183.     {
  1184.         illparams("fD_parsefd");
  1185.         return real_error;
  1186.     }
  1187. }
  1188.  
  1189. static void
  1190. fD_adjustargnames(fdDef *obj)
  1191. {
  1192.     int parnum;
  1193.  
  1194.     if (output_mode==NEW)
  1195.     {
  1196.  
  1197.         /* For #define-base output mode, we have to check if argument names are not
  1198.             the same as some words in type names. We check from the first argument
  1199.             to the last, resolving conflicts by changing argument names, if
  1200.             necessary. */
  1201.  
  1202.         for (parnum=0; parnum<fD_ParamNum(obj); parnum++)
  1203.         {
  1204.             const char *parname=fD_GetParam(obj, parnum);
  1205.             int finished;
  1206.             do
  1207.             {
  1208.                 int num;
  1209.                 const char *type=fD_GetType(obj);
  1210.                 char *str;
  1211.                 finished=1;
  1212.  
  1213.                 if ((str=strstr(type, parname))!=0 && (str==type ||
  1214.                 (!isalnum(str[-1]) && str[-1]!='_')) &&
  1215.                 (!*(str+=strlen(parname)) || (!isalnum(*str) && *str!='_')))
  1216.                 {
  1217.                     char buf[300]; /* Hope will be enough... */
  1218.                     strcpy(buf, parname);
  1219.                     strcat(buf, "_");
  1220.                     fD_NewParam(obj, parnum, buf);
  1221.                     finished=0;
  1222.                 }
  1223.                 else
  1224.                     for (num=0; num<fD_ParamNum(obj); num++)
  1225.                     {
  1226.                         const char *name=fD_GetParam(obj, num);
  1227.                         const char *proto=fD_GetProto(obj, num);
  1228.                         if ((num<parnum && strcmp(name, parname)==0) ||
  1229.                         ((str=strstr(proto, parname))!=0 && (str==proto ||
  1230.                         (!isalnum(str[-1]) && str[-1]!='_')) &&
  1231.                         (!*(str+=strlen(parname)) || (!isalnum(*str) && *str!='_'))))
  1232.                         {
  1233.                             char buf[300]; /* Hope will be enough... */
  1234.                             strcpy(buf, parname);
  1235.                             strcat(buf, "_");
  1236.                             fD_NewParam(obj, parnum, buf);
  1237.                             finished=0;
  1238.                             break;
  1239.                         }
  1240.                     }
  1241.             } while (!finished);
  1242.         }
  1243.     }
  1244. }
  1245.  
  1246. Error
  1247. fD_parsepr(fdDef* obj, fdFile* infile)
  1248. {
  1249.     char    *buf;        /* a copy of infile->line                            */
  1250.     char    *bpoint,    /* cursor in buf                                        */
  1251.             *bnext,    /* looking for the end                                */
  1252.             *lowarg;    /* beginning of this argument                        */
  1253.     long    obraces;    /* count of open braces                                */
  1254.     regs    count,    /* count parameter number                            */
  1255.             args;        /* the number of arguments for this function */
  1256.  
  1257.     if (!(obj && infile && fF_GetError(infile)==false))
  1258.     {
  1259.         illparams("fD_parsepr");
  1260.         fF_SetError(infile, real_error);
  1261.         return real_error;
  1262.     }
  1263.     if (!NewString(&buf, infile->line))
  1264.     {
  1265.         fprintf(stderr, "no mem for fD_parsepr\n");
  1266.         fF_SetError(infile, real_error);
  1267.         return real_error;
  1268.     }
  1269.     fF_SetError(infile, false);
  1270.  
  1271.     bpoint=strchr(buf, '(');
  1272.     while (--bpoint>=buf && strstr(bpoint, fD_GetName(obj))!=bpoint);
  1273.     if (bpoint>=buf)
  1274.     {
  1275.         while (--bpoint >= buf && (*bpoint==' ' || *bpoint=='\t'));
  1276.         *++bpoint='\0';
  1277.  
  1278.         fD_NewType(obj, buf);
  1279.  
  1280.         while (bpoint && *bpoint++!='('); /* one beyond '(' */
  1281.  
  1282.         lowarg=bpoint;
  1283.         obraces=0;
  1284.  
  1285.         for (count=0, args=fD_RegNum(obj); count<args; bpoint=bnext+1)
  1286.         {
  1287.             while (*bpoint && (*bpoint==' ' || *bpoint=='\t')) /* ignore spaces */
  1288.                 bpoint++;
  1289.  
  1290.             bnext=strpbrk(bpoint, "(),");
  1291.  
  1292.             if (bnext)
  1293.             {
  1294.                 switch (*bnext)
  1295.                 {
  1296.                     case '(':
  1297.                         if (!obraces)
  1298.                         {
  1299.                             if (fD_GetFuncParNum(obj)!=illegal &&
  1300.                             fD_GetFuncParNum(obj)!=count)
  1301.                                 fprintf(stderr, "Warning: two parameters of type "
  1302.                                     "pointer to function are used.\nThis is not "
  1303.                                     "supported!\n");
  1304.                             fD_SetFuncParNum(obj, count);
  1305.                         }
  1306.                         obraces++;
  1307.                         DBP(fprintf(stderr, "< (%ld%s >", obraces, bnext));
  1308.                         break;
  1309.  
  1310.                     case ')':
  1311.                         if (obraces)
  1312.                         {
  1313.                             DBP(fprintf(stderr, "< )%ld%s >", obraces, bnext));
  1314.                             obraces--;
  1315.                         }
  1316.                         else
  1317.                         {
  1318.                             *bnext='\0';
  1319.                             DBP(fprintf(stderr, "< )0> [LAST PROTO=%s]", lowarg));
  1320.                             fD_NewProto(obj, count, lowarg);
  1321.                             lowarg=bnext+1;
  1322.  
  1323.                             if (count!=args-1)
  1324.                             {
  1325.                                 DBP(fprintf(stderr, "%s needs %u arguments and got %u.\n",
  1326.                                     fD_GetName(obj), args, count+1));
  1327.                                 fF_SetError(infile, nodef);
  1328.                             }
  1329.                             count++;
  1330.                         }
  1331.                         break;
  1332.  
  1333.                     case ',':
  1334.                         if (!obraces)
  1335.                         {
  1336.                             *bnext='\0';
  1337.                             DBP(fprintf(stderr, " [PROTO=%s] ", lowarg));
  1338.                             fD_NewProto(obj, count, lowarg);
  1339.                             lowarg=bnext+1;
  1340.                             count++;
  1341.                         }
  1342.                         break;
  1343.  
  1344.                     default:
  1345.                         fprintf(stderr, "faulty strpbrk in line %lu.\n",
  1346.                             infile->lineno);
  1347.                 }
  1348.             }
  1349.             else
  1350.             {
  1351.                 DBP(fprintf(stderr, "faulty argument %u in line %lu.\n", count+1,
  1352.                     infile->lineno));
  1353.                 count=args; /* this will effectively quit the for loop */
  1354.                 fF_SetError(infile, nodef);
  1355.             }
  1356.         }
  1357.         if (fD_ProtoNum(obj)!=fD_RegNum(obj))
  1358.             fF_SetError(infile, nodef);
  1359.     }
  1360.     else
  1361.     {
  1362.         fprintf(stderr, "fD_parsepr was fooled in line %lu\n", infile->lineno);
  1363.         fprintf(stderr, "function , definition %s.\n",
  1364.             /* fD_GetName(obj),*/ infile->line);
  1365.         fF_SetError(infile, nodef);
  1366.     }
  1367.  
  1368.     free(buf);
  1369.  
  1370.     fD_adjustargnames(obj);
  1371.  
  1372.     return fF_GetError(infile);
  1373. }
  1374.  
  1375. int
  1376. fD_cmpName(const void* big, const void* small) /* for qsort and bsearch */
  1377. {
  1378.     return strcmp(fD_GetName(*(fdDef**)big), fD_GetName(*(fdDef**)small));
  1379. }
  1380.  
  1381. const static char *TagExcTable[]=
  1382. {
  1383.     "BuildEasyRequestArgs",    "BuildEasyRequest",
  1384.     "DoDTMethodA",                "DoDTMethod",
  1385.     "DoGadgetMethodA",        "DoGadgetMethod",
  1386.     "EasyRequestArgs",        "EasyRequest",
  1387.     "MUI_MakeObjectA",        "MUI_MakeObject",
  1388.     "MUI_RequestA",            "MUI_Request",
  1389.     "PrintDTObjectA",            "PrintDTObject",
  1390.     "UMSVLog",                    "UMSLog",
  1391.     "VFWritef",                    "FWritef",
  1392.     "VFPrintf",                    "FPrintf",
  1393.     "VPrintf",                    "Printf",
  1394. };
  1395.  
  1396. const char*
  1397. taggedfunction(const fdDef* obj)
  1398. {
  1399.     shortcard numregs=fD_RegNum(obj);
  1400.     unsigned int count;
  1401.     const char *name=fD_GetName(obj);
  1402.     static char newname[200];    /* Hope will be enough... static because used
  1403.                                             out of the function. */
  1404.     const char *lastarg;
  1405.     const static char *TagExcTable2[]=
  1406.     {
  1407.         "ApplyTagChanges",
  1408.         "CloneTagItems",
  1409.         "FindTagItem",
  1410.         "FreeTagItems",
  1411.         "GetTagData",
  1412.         "PackBoolTags",
  1413.         "PackStructureTags",
  1414.         "RefreshTagItemClones",
  1415.         "UnpackStructureTags",
  1416.     };
  1417.  
  1418.     if (!numregs)
  1419.         return NULL;
  1420.  
  1421.     for (count=0; count<sizeof TagExcTable/sizeof TagExcTable[0]; count+=2)
  1422.         if (strcmp(name, TagExcTable[count])==0)
  1423.             return TagExcTable[count+1];
  1424.  
  1425.     for (count=0; count<sizeof TagExcTable2/sizeof TagExcTable2[0]; count++)
  1426.         if (strcmp(name, TagExcTable2[count])==0)
  1427.             return NULL;
  1428.  
  1429.     lastarg=fD_GetProto(obj, numregs-1);
  1430.     if (strncmp(lastarg, "struct", 6))
  1431.         return NULL;
  1432.     lastarg+=6;
  1433.     while (*lastarg==' ' || *lastarg=='\t')
  1434.         lastarg++;
  1435.     if (strncmp(lastarg, "TagItem", 7))
  1436.         return NULL;
  1437.     lastarg+=7;
  1438.     while (*lastarg==' ' || *lastarg=='\t')
  1439.         lastarg++;
  1440.     if (strcmp(lastarg, "*"))
  1441.         return NULL;
  1442.  
  1443.     strcpy(newname, name);
  1444.     if (newname[strlen(newname)-1]=='A')
  1445.         newname[strlen(newname)-1]='\0';
  1446.     else
  1447.         if (strlen(newname)>7 && !strcmp(newname+strlen(newname)-7, "TagList"))
  1448.             strcpy(newname+strlen(newname)-4, "s");
  1449.         else
  1450.             strcat(newname, "Tags");
  1451.     return newname;
  1452. }
  1453.  
  1454. const char*
  1455. aliasfunction(const char* name)
  1456. {
  1457.     const static char *AliasTable[]=
  1458.     {
  1459.         "AllocDosObject",    "AllocDosObjectTagList",
  1460.         "CreateNewProc",    "CreateNewProcTagList",
  1461.         "NewLoadSeg",        "NewLoadSegTagList",
  1462.         "System",            "SystemTagList",
  1463.     };
  1464.     unsigned int count;
  1465.     for (count=0; count<sizeof AliasTable/sizeof AliasTable[0]; count++)
  1466.         if (strcmp(name, AliasTable[count])==0)
  1467.             return AliasTable[count+(count%2 ? -1 : 1)];
  1468.     return NULL;
  1469. }
  1470.  
  1471. void
  1472. fD_write(FILE* outfile, const fdDef* obj)
  1473. {
  1474.     shortcard count, numregs;
  1475.     const char *chtmp, *tagname, *name, *rettype;
  1476.     int vd=0, a45=0, d7=0;
  1477.  
  1478.     DBP(fprintf(stderr, "func %s\n", fD_GetName(obj)));
  1479.  
  1480.     numregs=fD_RegNum(obj);
  1481.  
  1482.     if ((rettype=fD_GetType(obj))==fD_nostring)
  1483.     {
  1484.         fprintf(stderr, "%s has no prototype.\n", fD_GetName(obj));
  1485.         return;
  1486.     }
  1487.     if (!stricmp(rettype, "void"))
  1488.         vd = 1; /* set flag */
  1489.     for (count=d0; count<numregs; count++)
  1490.     {
  1491.         const char *reg=fD_GetRegStr(obj, count);
  1492.         if (strcmp(reg, "a4")==0 || strcmp(reg, "a5")==0)
  1493.             if (!a45)
  1494.                 a45=(strcmp(reg, "a4") ? 5 : 4); /* set flag */
  1495.             else /* Security check */
  1496.                 fprintf(stderr, "Warning: both a4 and a5 are used. This is not "
  1497.                     "supported!\n");
  1498.         if (strcmp(reg, "d7")==0) /* Used only when a45!=0 */
  1499.             d7=1;
  1500.     }
  1501.     if (a45 && d7) /* Security check */
  1502.         fprintf(stderr, "Warning: d7 and a4 or a5 are used. This is not "
  1503.             "supported!\n");
  1504.  
  1505.     name=fD_GetName(obj);
  1506.  
  1507.     if (fD_ProtoNum(obj)!=numregs)
  1508.     {
  1509.         fprintf(stderr, "%s gets %d fd args and %d proto%s.\n", name, numregs,
  1510.             fD_ProtoNum(obj), fD_ProtoNum(obj)!= 1 ? "s" : "");
  1511.         return;
  1512.     }
  1513.  
  1514.     if ((output_mode==NEW) && (PowerUP==FALSE))
  1515.     {
  1516.         fprintf(outfile, "#define %s(", name);
  1517.  
  1518.         if (numregs>0)
  1519.         {
  1520.             for (count=d0; count<numregs-1; count++)
  1521.                 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1522.             fprintf(outfile, "%s", fD_GetParam(obj, count));
  1523.         }
  1524.  
  1525.         fprintf(outfile, ") \\\n\tLP%d%s%s%s%s(0x%lx, ", numregs,
  1526.             (vd ? "NR" : ""), (a45 ? (a45==4 ? "A4" : "A5") : ""),
  1527.             (BaseName[0] ? "" : "UB"),
  1528.             (fD_GetFuncParNum(obj)==illegal ? "" : "FP"), -fD_GetOffset(obj));
  1529.         if (!vd)
  1530.             fprintf(outfile, "%s, ", rettype);
  1531.         fprintf(outfile, "%s, ", name);
  1532.  
  1533.         for (count=d0; count<numregs; count++)
  1534.         {
  1535.             chtmp=fD_GetRegStr(obj, count);
  1536.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1537.                 chtmp="d7";
  1538.             fprintf(outfile, "%s, %s, %s%s", (fD_GetFuncParNum(obj)==count ?
  1539.                 "__fpt" : fD_GetProto(obj, count)), fD_GetParam(obj, count),
  1540.                 chtmp, (count==numregs-1 && !BaseName[0] ? "" : ", "));
  1541.         }
  1542.  
  1543.         if (BaseName[0]) /* was "##base" used? */
  1544.             fprintf(outfile, "\\\n\t, %s_BASE_NAME", BaseNamU);
  1545.         if (fD_GetFuncParNum(obj)!=illegal)
  1546.         {
  1547.             fprintf(outfile, ", ");
  1548.             fprintf(outfile, fD_GetProto(obj, fD_GetFuncParNum(obj)), "__fpt");
  1549.         }
  1550.         fprintf(outfile, ")\n\n");
  1551.     }
  1552.     else
  1553.     if ((output_mode==NEW) && (PowerUP==TRUE))
  1554.     {
  1555.         fprintf(outfile, "#define %s(", name);
  1556.  
  1557.         if (numregs>0)
  1558.         {
  1559.             for (count=d0; count<numregs-1; count++)
  1560.                 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1561.             fprintf(outfile, "%s", fD_GetParam(obj, count));
  1562.         }
  1563. /* A45 could be removed..but i let it stay so the M68k and PPC functions are the
  1564.  * the same
  1565.  */
  1566.         fprintf(outfile, ") \\\n\tLP%d%s%s%s%s(0x%lx, ", numregs,
  1567.             (vd ? "NR" : ""), (a45 ? (a45==4 ? "A4" : "A5") : ""),
  1568.             (BaseName[0] ? "" : "UB"),
  1569.             (fD_GetFuncParNum(obj)==illegal ? "" : "FP"), -fD_GetOffset(obj));
  1570.         if (!vd)
  1571.             fprintf(outfile, "%s, ", rettype);
  1572.         fprintf(outfile, "%s, ", name);
  1573.  
  1574.         for (count=d0; count<numregs; count++)
  1575.         {
  1576.             chtmp=fD_GetRegStr(obj, count);
  1577.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1578.                 chtmp="d7";
  1579.             fprintf(outfile, "%s, %s, %s%s", (fD_GetFuncParNum(obj)==count ?
  1580.                 "__fpt" : fD_GetProto(obj, count)), fD_GetParam(obj, count),
  1581.                 chtmp, (count==numregs-1 && !BaseName[0] ? "" : ", "));
  1582.         }
  1583.  
  1584.         if (BaseName[0]) /* was "##base" used? */
  1585.             fprintf(outfile, "\\\n\t, %s_BASE_NAME", BaseNamU);
  1586.         if (fD_GetFuncParNum(obj)!=illegal)
  1587.         {
  1588.             fprintf(outfile, ", ");
  1589.             fprintf(outfile, fD_GetProto(obj, fD_GetFuncParNum(obj)), "__fpt");
  1590.         }
  1591. /* Here it would make sense to create a database file to integrate optimizations
  1592.  * automaticly into every new build.
  1593.  * Not every function needs a complete flush. For example functions with no parameter
  1594.  * wouldn`t need a PPC flush normally.
  1595.  * Or Read(File,Addr,Size); would only need a flush for Addr with the Size
  1596.  */
  1597.         fprintf(outfile, ", IF_CACHEFLUSHALL, NULL, 0, IF_CACHEFLUSHALL, NULL, 0");
  1598.         fprintf(outfile, ")\n\n");
  1599.  
  1600.     }
  1601.     else if (output_mode==PRAGMA)
  1602.     {
  1603.         if (PowerUP==TRUE)
  1604.         {
  1605.  
  1606.             fprintf(outfile, "#define\t%s",
  1607.                 name);
  1608.  
  1609.             if (numregs)
  1610.             {
  1611.                 fprintf(outfile, "(");
  1612.  
  1613.                 if (numregs>0)
  1614.                 {
  1615.                     for (count=d0; count<numregs-1; count++)
  1616.                     {
  1617.                         fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1618.                     }
  1619.                     fprintf(outfile, "%s", fD_GetParam(obj, count));
  1620.                 }
  1621.  
  1622.                 fprintf(outfile, ")");
  1623.  
  1624.                 if (BaseName[0]) /* was "##base" used? */
  1625.                 {
  1626.                     fprintf(outfile, "\t_%s(%s_BASE_NAME%s",
  1627.                         name,
  1628.                         BaseNamU,
  1629.                         numregs ? ", " : "");
  1630.                 }
  1631.                 else
  1632.                 {
  1633.                     fprintf(outfile, "\t_%s(",
  1634.                         name);
  1635.                 }
  1636.  
  1637.                 if (numregs>0)
  1638.                 {
  1639.                     for (count=d0; count<numregs-1; count++)
  1640.                     {
  1641.                         fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1642.                     }
  1643.                     fprintf(outfile, "%s", fD_GetParam(obj, count));
  1644.                 }
  1645.  
  1646.                 fprintf(outfile, ")\n\n");
  1647.             }
  1648.             else
  1649.             {
  1650.                 if (BaseName[0]) /* was "##base" used? */
  1651.                 {
  1652.                     fprintf(outfile, "()\t_%s(%s_BASE_NAME)\n\n",
  1653.                         name,
  1654.                         BaseNamU);
  1655.                 }
  1656.                 else
  1657.                 {
  1658.                     fprintf(outfile, "()\t_%s()\n\n",
  1659.                         name);
  1660.                 }
  1661.             }
  1662.  
  1663.             fprintf(outfile, "static __inline %s\n_%s(%s%s%s",
  1664.                 rettype,
  1665.                 name,
  1666.                 BaseName[0] ? "void *" : "",
  1667.                 BaseName[0] ? BaseName : "",
  1668.                 (BaseName[0] ? (numregs ? ", " : "") : ""));
  1669.  
  1670.             for (count=d0; count<numregs; count++)
  1671.             {
  1672.                 chtmp=fD_GetProto(obj, count);
  1673.                 if (fD_GetFuncParNum(obj)==count)
  1674.                 {
  1675.                     fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1676.                 }
  1677.                 else
  1678.                 {
  1679.                     fprintf(outfile, "%s%s%s", chtmp, (*(chtmp+strlen(chtmp)-1)=='*' ?
  1680.                         "" : " "), fD_GetParam(obj, count));
  1681.                 }
  1682.                 if (count<numregs-1)
  1683.                 {
  1684.                     fprintf(outfile, ", ");    
  1685.                 }
  1686.             }
  1687.  
  1688.             fprintf(outfile, ")\n");
  1689.             fprintf(outfile, "{\n");
  1690.             fprintf(outfile, "struct Caos\tMyCaos;\n");
  1691.             fprintf(outfile, "\tMyCaos.M68kCacheMode\t=\tIF_CACHEFLUSHALL;\n");
  1692.             fprintf(outfile, "//\tMyCaos.M68kStart\t=\tNULL;\n");
  1693.             fprintf(outfile, "//\tMyCaos.M68kSize\t\t=\t0;\n");
  1694.             fprintf(outfile, "\tMyCaos.PPCCacheMode\t=\tIF_CACHEFLUSHALL;\n");
  1695.             fprintf(outfile, "//\tMyCaos.PPCStart\t\t=\tNULL;\n");
  1696.             fprintf(outfile, "//\tMyCaos.PPCSize\t\t=\t0;\n");
  1697.  
  1698.             if (numregs>0)
  1699.             {
  1700.                 for (count=d0; count<numregs; count++)
  1701.                 {
  1702.                     fprintf(outfile, "\tMyCaos.%s\t\t=(ULONG) %s;\n",
  1703.                        fD_GetRegStr(obj,count),
  1704.                            fD_GetParam(obj,count));
  1705.                 }
  1706.             }
  1707.  
  1708.             fprintf(outfile, "\tMyCaos.caos_Un.Offset\t=\t(%ld);\n",
  1709.                 fD_GetOffset(obj));
  1710.  
  1711.             if (BaseName[0]) /* was "##base" used? */
  1712.                     {
  1713.                 fprintf(outfile, "\tMyCaos.a6\t\t=(ULONG) %s;\t\n",
  1714.                     BaseName);
  1715.                     }
  1716.             if (vd)
  1717.             {
  1718.                 fprintf(outfile, "\tPPCCallOS(&MyCaos);\n}\n\n");
  1719.             }
  1720.             else
  1721.             {
  1722.                 fprintf(outfile, "\treturn((%s)PPCCallOS(&MyCaos));\n}\n\n",
  1723.                     rettype);
  1724. /*
  1725.                 fprintf(outfile, "\treturn((%s)MyCaos.d0);\n}\n\n",
  1726.                         rettype);
  1727. */
  1728.             }
  1729.  
  1730.         }
  1731.         else
  1732.         {
  1733.             /* No M68k support yet */
  1734.         }
  1735.     }
  1736.     else
  1737.     {
  1738.         if (PowerUP==TRUE)
  1739.         {
  1740.             fprintf(outfile, "%sstatic __inline %s\n%s(%s",
  1741.                 (output_mode==STUBS ? "" : "extern "), rettype, name,
  1742.                 (BaseName[0] ? (numregs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
  1743.  
  1744.             for (count=d0; count<numregs; count++)
  1745.             {
  1746.                 chtmp=fD_GetProto(obj, count);
  1747.                 if (fD_GetFuncParNum(obj)==count)
  1748.                     fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1749.                 else
  1750.                     fprintf(outfile, "%s%s%s", chtmp, (*(chtmp+strlen(chtmp)-1)=='*' ?
  1751.                         "" : " "), fD_GetParam(obj, count));
  1752.                 if (count<numregs-1)
  1753.                     fprintf(outfile, ", ");
  1754.             }
  1755.  
  1756.             fprintf(outfile, ")\t\n");
  1757.             fprintf(outfile, "{\t\n");
  1758.             fprintf(outfile, "struct Caos\tMyCaos;\n");
  1759.             fprintf(outfile, "\tMyCaos.M68kCacheMode\t=\tIF_CACHEFLUSHALL;\t\n");
  1760.             fprintf(outfile, "//\tMyCaos.M68kStart\t=\tNULL;\t\n");
  1761.             fprintf(outfile, "//\tMyCaos.M68kSize\t\t=\t0;\t\n");
  1762.             fprintf(outfile, "\tMyCaos.PPCCacheMode\t=\tIF_CACHEFLUSHALL;\t\n");
  1763.             fprintf(outfile, "//\tMyCaos.PPCStart\t\t=\tNULL;\t\n");
  1764.             fprintf(outfile, "//\tMyCaos.PPCSize\t\t=\t0;\t\n");
  1765.  
  1766.             if (numregs>0)
  1767.             {
  1768.                 for (count=d0; count<numregs; count++)
  1769.                 {
  1770.                     fprintf(outfile, "\tMyCaos.%s\t\t=(ULONG) %s;\t\n",
  1771.                        fD_GetRegStr(obj,count),
  1772.                            fD_GetParam(obj,count));
  1773.                 }
  1774.             }
  1775.  
  1776.             fprintf(outfile, "\tMyCaos.caos_Un.Offset\t=\t(%ld);\t\n",fD_GetOffset(obj));
  1777.             if (BaseName[0]) /* was "##base" used? */
  1778.                     {
  1779.                 fprintf(outfile, "\tMyCaos.a6\t\t=\t(ULONG) %s_BASE_NAME;\t\n",
  1780.                     BaseNamU);
  1781.                     }
  1782.             if (vd)
  1783.             {
  1784.                 fprintf(outfile, "\tPPCCallOS(&MyCaos);\t\n}\n\n");
  1785.             }
  1786.             else
  1787.             {
  1788.                 fprintf(outfile, "\treturn((%s)PPCCallOS(&MyCaos));\n}\n\n",
  1789.                     rettype);
  1790. /*
  1791.                 fprintf(outfile, "\treturn((%s)MyCaos.d0);\t\n}\n\n",
  1792.                         rettype);
  1793. */
  1794.             }
  1795.         }
  1796.         else
  1797.         {
  1798.             fprintf(outfile, "%s__inline %s\n%s(%s",
  1799.                 (output_mode==STUBS ? "" : "extern "), rettype, name,
  1800.                 (BaseName[0] ? (numregs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
  1801.  
  1802.             for (count=d0; count<numregs; count++)
  1803.             {
  1804.                 chtmp=fD_GetProto(obj, count);
  1805.                 if (fD_GetFuncParNum(obj)==count)
  1806.                     fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1807.                 else
  1808.                     fprintf(outfile, "%s%s%s", chtmp, (*(chtmp+strlen(chtmp)-1)=='*' ?
  1809.                         "" : " "), fD_GetParam(obj, count));
  1810.                 if (count<numregs-1)
  1811.                     fprintf(outfile, ", ");
  1812.             }
  1813.             fprintf(outfile, ")\n{\n%s", (BaseName[0] ? "   BASE_EXT_DECL\n" : ""));
  1814.             if (!vd)
  1815.                 fprintf(outfile, "   register %s%sres __asm(\"d0\");\n", rettype,
  1816.                     (*(rettype+strlen(rettype)-1)=='*' ? "" : " "));
  1817.  
  1818.             if (BaseName[0])
  1819.                 fprintf(outfile, "   register struct %s *a6 __asm(\"a6\") = BASE_NAME;\n",
  1820.                     StdLib);
  1821.  
  1822.             for (count=d0; count<numregs; count++)
  1823.             {
  1824.                 chtmp=fD_GetRegStr(obj, count);
  1825.                 if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1826.                     chtmp="d7";
  1827.                 if (fD_GetFuncParNum(obj)==count)
  1828.                 {
  1829.                     fprintf(outfile, "   register ");
  1830.                     fprintf(outfile, fD_GetProto(obj, count), chtmp);
  1831.                     fprintf(outfile, " __asm(\"%s\") = %s;\n", chtmp, fD_GetParam(obj,
  1832.                         count));
  1833.                 }
  1834.                 else
  1835.                 {
  1836.                     const char *proto=fD_GetProto(obj, count);
  1837.                     fprintf(outfile, "   register %s%s%s __asm(\"%s\") = %s;\n",
  1838.                         proto, (*(proto+strlen(proto)-1)=='*' ? "" : " "), chtmp,
  1839.                         chtmp, fD_GetParam(obj, count));
  1840.                 }
  1841.             }
  1842.             if (a45)
  1843.                 fprintf(outfile, "   __asm volatile (\"exg d7,%s\\n\\t"
  1844.                     "jsr a6@(-0x%lx:W)\\n\\texg d7,%s\"\n", (a45==4 ? "a4" : "a5"),
  1845.                     -fD_GetOffset(obj), (a45==4 ? "a4" : "a5"));
  1846.             else
  1847.                 fprintf(outfile, "   __asm volatile (\"jsr a6@(-0x%lx:W)\"\n",
  1848.                     -fD_GetOffset(obj));
  1849.  
  1850.             fprintf(outfile, (vd ? "   : /* No Output */\n" : "   : \"=r\" (res)\n"));
  1851.  
  1852.             fprintf(outfile, "   : ");
  1853.             if (BaseName[0])
  1854.                 fprintf(outfile, "\"r\" (a6)%s", (numregs ? ", ": ""));
  1855.  
  1856.             for (count=d0; count<numregs; count++)
  1857.             {
  1858.                 chtmp=fD_GetRegStr(obj, count);
  1859.                 if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1860.                     chtmp="d7";
  1861.                 fprintf(outfile, "\"r\" (%s)%s", chtmp, (count<numregs-1 ? ", " : ""));
  1862.             }
  1863.             fprintf(outfile, "\n   : \"d0\", \"d1\", \"a0\", \"a1\", \"fp0\", \"fp1\"");
  1864.  
  1865.             if (vd)
  1866.                 fprintf(outfile, ", \"cc\", \"memory\");\n}\n\n"); /* { */
  1867.             else
  1868.                 fprintf(outfile, ", \"cc\", \"memory\");\n   return res;\n}\n\n");
  1869.         }
  1870.     }
  1871.  
  1872.     if ((tagname=aliasfunction(fD_GetName(obj)))!=0)
  1873.     {
  1874.         fprintf(outfile, "#define %s(", tagname);
  1875.         for (count=d0; count<numregs-1; count++)
  1876.             fprintf(outfile, "a%d, ", count);
  1877.         fprintf(outfile, "a%d) %s (", count, name);
  1878.         for (count=d0; count<numregs-1; count++)
  1879.             fprintf(outfile, "(a%d), ", count);
  1880.         fprintf(outfile, "(a%d))\n\n", count);
  1881.     }
  1882.  
  1883.     if ((tagname=taggedfunction(obj))!=0)
  1884.     {
  1885.         if (output_mode!=STUBS)
  1886.         {
  1887.             if (PowerUP)
  1888.             {
  1889.                 fprintf(outfile, "#ifndef NO_PPCINLINE_STDARG\n#define %s(", tagname);
  1890.             }
  1891.             else
  1892.             {
  1893.                 fprintf(outfile, "#ifndef NO_INLINE_STDARG\n#define %s(", tagname);
  1894.             }
  1895.  
  1896.             for (count=d0; count<numregs-1; count++)
  1897.                 fprintf(outfile, "a%d, ", count);
  1898.  
  1899.             fprintf(outfile, "tags...) \\\n\t({ULONG _tags[] = { tags }; %s(",
  1900.                 name);
  1901.  
  1902.             for (count=d0; count<numregs-1; count++)
  1903.                 fprintf(outfile, "(a%d), ", count);
  1904.  
  1905.             if (PowerUP)
  1906.             {
  1907.                 fprintf(outfile, "(%s)_tags);})\n#endif /* !NO_PPCINLINE_STDARG */\n\n",
  1908.                     fD_GetProto(obj, fD_RegNum(obj)-1));
  1909.             }
  1910.             else
  1911.             {
  1912.                 fprintf(outfile, "(%s)_tags);})\n#endif /* !NO_INLINE_STDARG */\n\n",
  1913.                     fD_GetProto(obj, fD_RegNum(obj)-1));
  1914.             }
  1915.         }
  1916.         else
  1917.         {
  1918.             fprintf(outfile, "%s %s(", rettype, tagname);
  1919.  
  1920.             for (count=d0; count<numregs-1; count++)
  1921.             {
  1922.                 chtmp=fD_GetProto(obj, count);
  1923.                 if (count==fD_GetFuncParNum(obj))
  1924.                     fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1925.                 else
  1926.                     fprintf(outfile, "%s%s%s", chtmp,
  1927.                         (*(chtmp+strlen(chtmp)-1)=='*' ? "" : " "),
  1928.                         fD_GetParam(obj, count));
  1929.                 fprintf(outfile, ", ");
  1930.             }
  1931.  
  1932.             fprintf(outfile, "int tag, ...)\n{\n   ");
  1933.             if (!vd)
  1934.                 fprintf(outfile, "return ");
  1935.  
  1936.             fprintf(outfile, "%s(", name);
  1937.             for (count=d0; count<numregs-1; count++)
  1938.                 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1939.  
  1940.             fprintf(outfile, "(%s)&tag);\n}\n\n", fD_GetProto(obj, fD_RegNum(obj)-1));
  1941.         }
  1942.     }
  1943.  
  1944.     if (strcmp(name, "DoPkt")==0)
  1945.     {
  1946.         fdDef *objnc=(fdDef*)obj;
  1947.         char newname[7]="DoPkt0";
  1948.         objnc->name=newname;
  1949.         for (count=2; count<7; count++)
  1950.         {
  1951.             regs reg=objnc->reg[count];
  1952.             char *proto=objnc->proto[count];
  1953.             objnc->reg[count]=illegal;
  1954.             objnc->proto[count]=fD_nostring;
  1955.             fD_write(outfile, objnc);
  1956.             objnc->reg[count]=reg;
  1957.             objnc->proto[count]=proto;
  1958.             newname[5]++;
  1959.         }
  1960.         objnc->name=(char*)name;
  1961.     }
  1962. }
  1963.  
  1964. int
  1965. varargsfunction(const char* proto, const char* funcname)
  1966. {
  1967.     const char *end=proto+strlen(proto)-1;
  1968.     while (isspace(*end))
  1969.         end--;
  1970.     if (*end--==';')
  1971.     {
  1972.         while (isspace(*end))
  1973.             end--;
  1974.         if (*end--==')')
  1975.         {
  1976.             while (isspace(*end))
  1977.                 end--;
  1978.             if (!strncmp(end-2, "...", 3))
  1979.             {
  1980.                 /* Seems to be a varargs function. Check if it will be recognized
  1981.                     as "tagged". */
  1982.                 unsigned int count;
  1983.                 char fixedname[200]; /* Hope will be enough... */
  1984.                 fdDef *tmpdef;
  1985.  
  1986.                 for (count=0; count<sizeof TagExcTable/sizeof TagExcTable[0];
  1987.                 count+=2)
  1988.                     if (strcmp(funcname, TagExcTable[count+1])==0)
  1989.                         return 1;
  1990.  
  1991.                 if (!(tmpdef=fD_ctor()))
  1992.                 {
  1993.                     fprintf(stderr, "No mem for FDs\n");
  1994.                     exit(EXIT_FAILURE);
  1995.                 }
  1996.  
  1997.                 strcpy(fixedname, funcname);
  1998.                 if (strlen(funcname)>4 &&
  1999.                 !strcmp(funcname+strlen(funcname)-4, "Tags"))
  2000.                 {
  2001.                     /* Might be either nothing or "TagList". */
  2002.                     fixedname[strlen(fixedname)-4]='\0';
  2003.                     fD_NewName(tmpdef, fixedname);
  2004.                     if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  2005.                     fD_cmpName))
  2006.                         return 1;
  2007.  
  2008.                     strcat(fixedname, "TagList");
  2009.                     fD_NewName(tmpdef, fixedname);
  2010.                     if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  2011.                     fD_cmpName))
  2012.                         return 1;
  2013.                 }
  2014.                 else
  2015.                 {
  2016.                     strcat(fixedname, "A");
  2017.                     fD_NewName(tmpdef, fixedname);
  2018.                     if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  2019.                     fD_cmpName))
  2020.                         return 1;
  2021.                 }
  2022.             }
  2023.         }
  2024.     }
  2025.     return 0;
  2026. }
  2027.  
  2028. int
  2029. ishandleddifferently(const char* proto, const char* funcname)
  2030. {
  2031.     /* First check if this is a vararg call? */
  2032.     if (varargsfunction(proto, funcname))
  2033.         return 1;
  2034.  
  2035.     /* It might be a dos.library "alias" name. */
  2036.     if (aliasfunction(funcname))
  2037.         return 1;
  2038.  
  2039.     /* It might be one from dos.library/DoPkt() family. */
  2040.     if (strlen(funcname)==6 && !strncmp(funcname, "DoPkt", 5) &&
  2041.     funcname[5]>='0' && funcname[6]<='4')
  2042.         return 1;
  2043.  
  2044.     /* Finally, it can be intuition.library/ReportMouse1(). */
  2045.     return !strcmp(funcname, "ReportMouse1");
  2046. }
  2047.  
  2048. void
  2049. printusage(const char* exename)
  2050. {
  2051.     fprintf(stderr,
  2052.         "Usage: %s [options] fd-file clib-file [[-o] output-file]\n"
  2053.         "Options:\n"
  2054.         "--new\t\tpreprocessor based (default)\n"
  2055.         "--old\t\tinline based\n"
  2056.         "--stubs\t\tlibrary stubs\n"
  2057.         "--proto\t\tbuild proto files (no clib-file required)\n"
  2058.         "--pragma\t\tbuild pragma file\n"
  2059.         "--powerup\t\tpowerup flag\n"
  2060.         "--version\tprint version number and exit\n", exename);
  2061. }
  2062.  
  2063. void output_proto(FILE* outfile)
  2064. {
  2065.     if (PowerUP)
  2066.     {
  2067.         fprintf(outfile,
  2068.             "/* Automatically generated header! Do not edit! */\n\n"
  2069.             "#ifndef PPCPROTO_%s_H\n"
  2070.             "#define PPCPROTO_%s_H\n\n"
  2071.             "#include <clib/%s_protos.h>\n\n"
  2072.             "#ifdef __GNUC__\n"
  2073.             "#include <powerup/ppcinline/%s.h>\n"
  2074.             "#endif /* __GNUC__ */\n\n",
  2075.             BaseNamU, BaseNamU, BaseNamL, BaseNamL);
  2076.     }
  2077.     else
  2078.     {
  2079.         fprintf(outfile,
  2080.             "/* Automatically generated header! Do not edit! */\n\n"
  2081.             "#ifndef PROTO_%s_H\n"
  2082.             "#define PROTO_%s_H\n\n"
  2083.             "#include <clib/%s_protos.h>\n\n"
  2084.             "#ifdef __GNUC__\n"
  2085.             "#include <inline/%s.h>\n"
  2086.             "#endif /* __GNUC__ */\n\n",
  2087.             BaseNamU, BaseNamU, BaseNamL, BaseNamL);
  2088.     }
  2089.     if (BaseName[0])
  2090.         fprintf(outfile,
  2091.             "#ifndef __NOLIBBASE__\n"
  2092.             "extern struct %s *\n"
  2093.             "#ifdef __CONSTLIBBASEDECL__\n"
  2094.             "__CONSTLIBBASEDECL__\n"
  2095.             "#endif /* __CONSTLIBBASEDECL__ */\n"
  2096.             "%s;\n"
  2097.             "#endif /* !__NOLIBBASE__ */\n\n",
  2098.             StdLib, BaseName);
  2099.  
  2100.     if (PowerUP)
  2101.     {
  2102.         fprintf(outfile,
  2103.             "#endif /* !PPCPROTO_%s_H */\n", BaseNamU);
  2104.     }
  2105.     else
  2106.     {
  2107.         fprintf(outfile,
  2108.             "#endif /* !PROTO_%s_H */\n", BaseNamU);
  2109.     }
  2110. }
  2111.  
  2112. /******************************************************************************/
  2113.  
  2114. int
  2115. main(int argc, char** argv)
  2116. {
  2117.     fdDef *tmpdef,            /* a dummy to contain the name to look for */
  2118.         *founddef;        /* the fdDef for which we found a prototype */
  2119.     fdFile *myfile;
  2120.     char *tmpstr;
  2121.     FILE *outfile;
  2122.     char *fdfilename=0, *clibfilename=0, *outfilename=0;
  2123.  
  2124.     int count;
  2125.     Error lerror;
  2126.  
  2127.     for (count=1; count<argc; count++)
  2128.     {
  2129.         char *option=argv[count];
  2130.         if (*option=='-')
  2131.         {
  2132.             option++;
  2133.             if (strcmp(option, "o")==0)
  2134.             {
  2135.                 if (count==argc-1 || outfilename)
  2136.                 {
  2137.                     printusage(argv[0]);
  2138.                     return EXIT_FAILURE;
  2139.                 }
  2140.                 if (strcmp(argv[++count], "-"))
  2141.                     outfilename=argv[count];
  2142.             }
  2143.             else
  2144.             {
  2145.                 if (*option=='-') /* Accept GNU-style '--' options */
  2146.                     option++;
  2147.                 if (strcmp(option, "new")==0)
  2148.                     output_mode=NEW;
  2149.                 else if (strcmp(option, "old")==0)
  2150.                     output_mode=OLD;
  2151.                 else if (strcmp(option, "stubs")==0)
  2152.                     output_mode=STUBS;
  2153.                 else if (strcmp(option, "proto")==0)
  2154.                     output_mode=PROTO;
  2155.                 else if (strcmp(option, "pragma")==0)
  2156.                     output_mode=PRAGMA;
  2157.                 else if (strcmp(option, "powerup")==0)
  2158.                     PowerUP    =    TRUE;
  2159.                 else if (strcmp(option, "version")==0)
  2160.                 {
  2161.                     fprintf(stderr, "fd2inline version " VERSION "\n");
  2162.                     return EXIT_SUCCESS;
  2163.                 }
  2164.                 else
  2165.                 {
  2166.                     printusage(argv[0]);
  2167.                     return EXIT_FAILURE;
  2168.                 }
  2169.             }
  2170.         }
  2171.         else
  2172.         {
  2173.             /* One of the filenames */
  2174.             if (!fdfilename)
  2175.                 fdfilename=option;
  2176.             else if (!clibfilename)
  2177.                 clibfilename=option;
  2178.             else if (!outfilename)
  2179.                 outfilename=option;
  2180.             else
  2181.             {
  2182.                 printusage(argv[0]);
  2183.                 return EXIT_FAILURE;
  2184.             }
  2185.         }
  2186.     }
  2187.  
  2188.     if (!fdfilename || (!clibfilename && output_mode!=PROTO))
  2189.     {
  2190.         printusage(argv[0]);
  2191.         return EXIT_FAILURE;
  2192.     }
  2193.  
  2194.     if (!(arrdefs=malloc(FDS*sizeof(fdDef*))))
  2195.     {
  2196.         fprintf(stderr, "No mem for FDs\n");
  2197.         return EXIT_FAILURE;
  2198.     }
  2199.     for (count=0; count<FDS; count++)
  2200.         arrdefs[count]=NULL;
  2201.  
  2202.     if (!(myfile=fF_ctor(fdfilename)))
  2203.     {
  2204.         fprintf(stderr, "Couldn't open file '%s'.\n", fdfilename);
  2205.         return EXIT_FAILURE;
  2206.     }
  2207.  
  2208.     lerror=false;
  2209.  
  2210.     for (count=0; count<FDS && lerror==false; count++)
  2211.     {
  2212.         if (!(arrdefs[count]=fD_ctor()))
  2213.         {
  2214.             fprintf(stderr, "No mem for FDs\n" );
  2215.             return EXIT_FAILURE;
  2216.         }
  2217.         do
  2218.         {
  2219.             if ((lerror=fF_readln(myfile))==false)
  2220.             {
  2221.                 fF_SetError(myfile, false);
  2222.                 lerror=fD_parsefd(arrdefs[count], myfile);
  2223.             }
  2224.         }
  2225.         while (lerror==nodef);
  2226.     }
  2227.     if (count<FDS)
  2228.     {
  2229.         count--;
  2230.         fD_dtor(arrdefs[count]);
  2231.         arrdefs[count]=NULL;
  2232.     }
  2233.     fds=count;
  2234.  
  2235.     qsort(arrdefs, count, sizeof arrdefs[0], fD_cmpName);
  2236.  
  2237.     if (output_mode!=NEW)
  2238.     {
  2239.         unsigned int count2;
  2240.         StdLib="Library";
  2241.  
  2242.         for (count2=0; count2<sizeof LibExcTable/sizeof LibExcTable[0]; count2+=2)
  2243.             if (strcmp(BaseName, LibExcTable[count2])==0)
  2244.             {
  2245.                 StdLib=LibExcTable[count2+1];
  2246.                 break;
  2247.             }
  2248.     }
  2249.  
  2250.     fF_dtor(myfile);
  2251.  
  2252.     if (output_mode!=PROTO)
  2253.     {
  2254.         if (!(myfile=fF_ctor(clibfilename)))
  2255.         {
  2256.             fprintf(stderr, "Couldn't open file '%s'.\n", clibfilename);
  2257.             return EXIT_FAILURE;
  2258.         }
  2259.  
  2260.         if (!(tmpdef=fD_ctor()))
  2261.         {
  2262.             fprintf(stderr, "No mem for FDs\n");
  2263.             return EXIT_FAILURE;
  2264.         }
  2265.  
  2266.         for (lerror=false; lerror==false || lerror==nodef;)
  2267.             if ((lerror=fF_readln(myfile))==false)
  2268.             {
  2269.                 fF_SetError(myfile, false); /* continue even on errors */
  2270.                 tmpstr=fF_FuncName(myfile);
  2271.  
  2272.                 if (tmpstr)
  2273.                 {
  2274.                    fdDef **res;
  2275.                     fD_NewName(tmpdef, tmpstr);
  2276.                     res=(fdDef**)bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  2277.                         fD_cmpName);
  2278.  
  2279.                     if (res)
  2280.                     {
  2281.                         founddef=*res;
  2282.                         DBP(fprintf(stderr, "found (%s).\n", fD_GetName(founddef)));
  2283.                         fF_SetError(myfile, false);
  2284.                         lerror=fD_parsepr(founddef, myfile);
  2285.                     }
  2286.                     else
  2287.                         if (!ishandleddifferently(myfile->line, tmpstr))
  2288.                             fprintf(stderr, "don't know what to do with <%s> in line %lu.\n",
  2289.                                 tmpstr, myfile->lineno);
  2290.                     free(tmpstr);
  2291.                 }
  2292.             }
  2293.  
  2294.         fD_dtor(tmpdef);
  2295.  
  2296.         fF_dtor(myfile);
  2297.     }
  2298.  
  2299.     if (strlen(fdfilename)>7 &&
  2300.     !strcmp(fdfilename+strlen(fdfilename)-7, "_lib.fd"))
  2301.     {
  2302.         char *str=fdfilename+strlen(fdfilename)-8;
  2303.         while (str!=fdfilename && str[-1]!='/' && str[-1]!=':')
  2304.             str--;
  2305.         strncpy(BaseNamL, str, strlen(str)-7);
  2306.         strncpy(BaseNamU, str, strlen(str)-7);
  2307.         BaseNamU[strlen(str)-7]='\0';
  2308.     }
  2309.     else
  2310.     {
  2311.         /* Shouldn't really happen, but... */
  2312.         strcpy(BaseNamU, BaseName);
  2313.         if (strlen(BaseNamU)>4 && strcmp(BaseNamU+strlen(BaseNamU)-4, "Base")==0)
  2314.             BaseNamU[strlen(BaseNamU)-4]='\0';
  2315.     }
  2316.     StrUpr(BaseNamU);
  2317.  
  2318.     if (outfilename)
  2319.     {
  2320.         if (!(outfile=fopen(outfilename, "w")))
  2321.         {
  2322.             fprintf(stderr, "Couldn't open output file.\n");
  2323.             return EXIT_FAILURE;
  2324.         }
  2325.     }
  2326.     else
  2327.         outfile=stdout;
  2328.  
  2329.     if (output_mode==PROTO)
  2330.     {
  2331.         output_proto(outfile);
  2332.     }
  2333.     else
  2334.     {
  2335.         if (output_mode==NEW)
  2336.         {
  2337.             if (PowerUP)
  2338.             {
  2339.                 fprintf(outfile,
  2340.                     "/* Automatically generated header! Do not edit! */\n\n"
  2341.                     "#ifndef _PPCINLINE_%s_H\n"
  2342.                     "#define _PPCINLINE_%s_H\n\n"
  2343.                     "#ifndef __PPCINLINE_MACROS_H\n"
  2344.                     "#include <powerup/ppcinline/macros.h>\n"
  2345.                     "#endif /* !__PPCINLINE_MACROS_H */\n\n",
  2346.                     BaseNamU,
  2347.                     BaseNamU);
  2348.             }
  2349.             else
  2350.             {
  2351.                 fprintf(outfile,
  2352.                     "/* Automatically generated header! Do not edit! */\n\n"
  2353.                     "#ifndef _INLINE_%s_H\n"
  2354.                     "#define _INLINE_%s_H\n\n"
  2355.                     "#ifndef __INLINE_MACROS_H\n"
  2356.                     "#include <inline/macros.h>\n"
  2357.                     "#endif /* !__INLINE_MACROS_H */\n\n",
  2358.                     BaseNamU,
  2359.                     BaseNamU);
  2360.             }
  2361.         }
  2362.         else if (output_mode==PRAGMA)
  2363.         {
  2364.             if (PowerUP)
  2365.             {
  2366.                 fprintf(outfile,
  2367.                     "/* Automatically generated header! Do not edit! */\n\n"
  2368.                     "#ifndef _PPCPRAGMA_%s_H\n"
  2369.                     "#define _PPCPRAGMA_%s_H\n"
  2370.                     "#ifdef __GNUC__\n"
  2371.                     "#ifndef _PPCINLINE__%s_H\n"
  2372.                     "#include <powerup/ppcinline/%s.h>\n"
  2373.                     "#endif\n"
  2374.                     "#else\n\n"
  2375.                     "#ifndef POWERUP_PPCLIB_INTERFACE_H\n"
  2376.                     "#include <powerup/ppclib/interface.h>\n"
  2377.                     "#endif\n\n"
  2378.                     "#ifndef POWERUP_GCCLIB_PROTOS_H\n"
  2379.                     "#include <powerup/gcclib/powerup_protos.h>\n"
  2380.                     "#endif\n\n"
  2381.                     "#ifndef NO_PPCINLINE_STDARG\n"
  2382.                     "#define NO_PPCINLINE_STDARG\n"
  2383.                     "#endif"
  2384.                     "/* SAS C PPC inlines */\n\n",
  2385.                     BaseNamU,
  2386.                     BaseNamU,
  2387.                     BaseNamU,
  2388.                     BaseNamL);
  2389.             }
  2390.             else
  2391.             {
  2392.                 fprintf(outfile,
  2393.                     "/* Automatically generated header! Do not edit! */\n\n"
  2394.                     "#ifndef _INLINE__%s_H\n"
  2395.                     "#include <inline/%s.h>\n\n",
  2396.                     BaseNamU,
  2397.                     BaseNamL);
  2398.             }
  2399.  
  2400.         }
  2401.         else
  2402.         {
  2403.             if (PowerUP)
  2404.             {
  2405.                 fprintf(outfile,
  2406.                     "/* Automatically generated header! Do not edit! */\n\n"
  2407.                     "#ifndef _PPCINLINE_%s_H\n"
  2408.                     "#define _PPCINLINE_%s_H\n\n"
  2409.                     "#ifndef __PPCINLINE_STUB_H\n"
  2410.                     "#include <powerup/ppcinline/stubs.h>\n"
  2411.                     "#endif /* !__PPCINLINE_STUB_H */\n\n",
  2412.                     BaseNamU,
  2413.                     BaseNamU);
  2414.             }
  2415.             else
  2416.             {
  2417.                 fprintf(outfile,
  2418.                     "/* Automatically generated header! Do not edit! */\n\n"
  2419.                     "#ifndef _INLINE_%s_H\n"
  2420.                     "#define _INLINE_%s_H\n\n"
  2421.                     "#ifndef __INLINE_STUB_H\n"
  2422.                     "#include <inline/stubs.h>\n"
  2423.                     "#endif /* !__INLINE_STUB_H */\n\n",
  2424.                     BaseNamU,
  2425.                     BaseNamU);
  2426.             }
  2427.         }
  2428.  
  2429.         if (BaseName[0])
  2430.         {
  2431.             if (output_mode==NEW || (output_mode==PRAGMA && PowerUP==TRUE))
  2432.             {
  2433.                 fprintf(outfile,
  2434.                     "#ifndef %s_BASE_NAME\n"
  2435.                     "#define %s_BASE_NAME %s\n"
  2436.                     "#endif /* !%s_BASE_NAME */\n\n",
  2437.                     BaseNamU, BaseNamU, BaseName, BaseNamU);
  2438.             }
  2439.             else
  2440.             {
  2441.                 fprintf(outfile,
  2442.                     "#ifndef BASE_EXT_DECL\n"
  2443.                     "#define BASE_EXT_DECL\n"
  2444.                     "#define BASE_EXT_DECL0 extern struct %s *%s;\n"
  2445.                     "#endif /* !BASE_EXT_DECL */\n"
  2446.                     "#ifndef BASE_PAR_DECL\n"
  2447.                     "#define BASE_PAR_DECL\n"
  2448.                     "#define BASE_PAR_DECL0 void\n"
  2449.                     "#endif /* !BASE_PAR_DECL */\n"
  2450.                     "#ifndef BASE_NAME\n"
  2451.                     "#define BASE_NAME %s\n"
  2452.                     "#endif /* !BASE_NAME */\n\n"
  2453.                     "BASE_EXT_DECL0\n\n", StdLib, BaseName, BaseName);
  2454.             }
  2455.         }
  2456.  
  2457.         for (count=0; count<FDS && arrdefs[count]; count++)
  2458.         {
  2459.             DBP(fprintf(stderr, "outputting %ld...\n", count));
  2460.  
  2461.             fD_write(outfile, arrdefs[count]);
  2462.             fD_dtor(arrdefs[count]);
  2463.             arrdefs[count]=NULL;
  2464.         }
  2465.  
  2466.         if (output_mode==OLD || output_mode==STUBS)
  2467.         {
  2468.             if (BaseName[0])
  2469.             {
  2470.                 fprintf(outfile,
  2471.                     "#undef BASE_EXT_DECL\n"
  2472.                     "#undef BASE_EXT_DECL0\n"
  2473.                     "#undef BASE_PAR_DECL\n"
  2474.                     "#undef BASE_PAR_DECL0\n"
  2475.                     "#undef BASE_NAME\n\n");
  2476.             }
  2477.  
  2478.             if (PowerUP)
  2479.             {
  2480.                 fprintf(outfile, "#endif /* !_PPCINLINE_%s_H */\n", BaseNamU);
  2481.             }
  2482.             else
  2483.             {
  2484.                 fprintf(outfile, "#endif /* !_INLINE_%s_H */\n", BaseNamU);
  2485.             }
  2486.         }
  2487.         else
  2488.         if (output_mode==PRAGMA)
  2489.         {
  2490.             fprintf(outfile, "#endif /* SASC Pragmas */\n");
  2491.             if (PowerUP)
  2492.             {
  2493.                 fprintf(outfile, "#endif /* !_PPCPRAGMA_%s_H */\n", BaseNamU);
  2494.             }
  2495.             else
  2496.             {
  2497.                 fprintf(outfile, "#endif /* !_PRAGMA_%s_H */\n", BaseNamU);
  2498.             }
  2499.         }
  2500.         else
  2501.         if (output_mode==NEW)
  2502.         {
  2503.             if (PowerUP)
  2504.             {
  2505.                 fprintf(outfile, "#endif /* !_PPCINLINE_%s_H */\n", BaseNamU);
  2506.             }
  2507.             else
  2508.             {
  2509.                 fprintf(outfile, "#endif /* !_INLINE_%s_H */\n", BaseNamU);
  2510.             }
  2511.         }
  2512.  
  2513.     }
  2514.  
  2515.     free(arrdefs);
  2516.  
  2517.     return EXIT_SUCCESS;
  2518. }
  2519.